home *** CD-ROM | disk | FTP | other *** search
- ;* VARS.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Vector & Variable support (interpreter support) *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 5 Feb 88: MEMV, ASSV use EQV's definition of number equality *
- ;* (which is "=", *not* "equal"). (rb) *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL small
- LOCALS @@
-
- INCLUDE "scheme.ash"
- INCLUDE "interprt.ash"
-
- CODESEG
- ;************************************************************************
- ;* Lookup Symbol is Assoc List *
- ;* *
- ;* Purpose: To search a linked list for a given pointer *
- ;* *
- ;* Description: The list to be searched has the following format: *
- ;* *
- ;* +--------+--------+ +--------+-------+ *
- ;* +-->|symbol->|value ->| +-->|symbol->|value->| *
- ;* | +--------+--------+ | +--------+-------+ *
- ;* | | *
- ;* +---+----+--------+ +---+----+--------+ *
- ;* | o | o----+----...----->| o | (nil) | *
- ;* +--------+--------+ +--------+--------+ *
- ;* *
- ;* The symbol portion of the list entries are compared against the *
- ;* search symbol for an identical match. When found, a pointer to *
- ;* the matched symbol's symbol-value entry is returned. If the *
- ;* symbol is not found, a value of nil is returned. *
- ;* *
- ;* Registers upon entry: ax - search symbol's displacement *
- ;* bx - page number of list to search *
- ;* dl - search symbol's page number *
- ;* si - displacement within page number *
- ;* of list to search *
- ;* *
- ;* Registers on exit: bl - page number of cell whose car is the *
- ;* search symbol, or zero if not found *
- ;* di - displacement of list cell found, or nil *
- ;* es:[di] - points to cell found *
- ;************************************************************************
- PROC lookup FAR
- @@loop:
- mov cx, bx ; Save Page number
- ldpage es, bx
- mov bl, [(LISTDEF es:si).car.page]
- mov di, [(LISTDEF es:si).car.disp]
- cmp [ptype+bx], LISTTYPE
- jne @@error
- ldpage es, bx
- cmp ax, [(LISTDEF es:di).car.disp]
- jne @@notfound
- cmp dl, [(LISTDEF es:di).car.page]
- je @@found
- @@notfound:
- mov bx, cx ; restore page number
- ldpage es, bx
- mov bl, [(LISTDEF es:si).cdr.page]
- cmp [ptype+bx], LISTTYPE
- jne @@error
- mov si, [(LISTDEF es:si).cdr.disp]
- or bx, bx
- jnz @@loop
- xor di, di ; make bx:di nil
- @@found:
- ret
- @@error:
- xor bx, bx ; create a nil pointer to return
- xor si, si
- ret
- ENDP lookup
-
- ;************************************************************************
- ;* Macro support for global/fluid variable lookup *
- ;************************************************************************
- MACRO load reg_p
- get2op
- save <si>
- mov bl, al ; copy destination register number to di
- mov di, bx
- mov bl, ah ; isolate constant number
- IFIDN <reg_p>, <REG>
- mov si, [regs+bx.page]
- mov ax, [regs+bx.disp]
- ELSE
- mov ax, bx ; bx <- constant number * 3
- shl ax, 1
- add bx, ax
- add bx, [cb_reg.disp] ; make displacement relative
- xor ax, ax
- mov al, [(CODEDEF es:bx).consts.page]
- mov si, ax
- mov ax, [(CODEDEF es:bx).consts.disp]
- ENDIF
- cmp [ptype+si], SYMBTYPE
- jne @@error
- push di
- mov dx, si ; copy symbol's page number into dx
- mov di, [fnv_reg.page]
- mov si, [fnv_reg.disp]
- mov bx, di ; bx <= page number
- call lookup ; search the environment for symbol
- or bx, bx ; symbol found ?
- pop bx ; restore register number
- je @@notfound
- mov ax, [(LISTDEF es:di).cdr.disp] ; load value
- mov dl, [(LISTDEF es:di).cdr.page]
- mov [regs+bx.disp], ax
- mov [regs+bx.bpage], dl
- jmp next_pc
- ENDM
-
- ;************************************************************************
- ;* al ah *
- ;* Fluid lookup FLUID dest, const *
- ;* *
- ;* Purpose: Interpreter support for fluid variable lookup *
- ;************************************************************************
- PROC ld_fluid
- load CONST
- @@error:
- lea bx, [fluidmsg]
- DATASEG
- fluidmsg DB "LD-FLUID", 0
- CODESEG
- jmp src_err
- @@notfound:
- in_ld_fluid:
- lea cx, [fnv_reg]
- corpage dx ; adjust page number for call to C routine
- add bx, OFFSET regs ; compute address of destination register
- call sym_undefined C, dx, ax, cx, bx
- restore <si>
- sub si, 3 ; back up PC to retry fluid load
- jmp sch_err
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Fluid lookup-register operand FLUID-R dest, sym *
- ;* *
- ;* Purpose: Interpreter support for fluid variable lookup *
- ;************************************************************************
- PROC ld_fl_r
- load REG
- @@error:
- lea bx, [fluidmsg]
- jmp src_err
- @@notfound:
- jmp in_ld_fluid
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* set-fluid! ST-FLUID src, const *
- ;* *
- ;* Purpose: Interpreter support for fluid assignment. *
- ;************************************************************************
- PROC st_fluid
- get2op
- save <si>
- push ax ; save symbol/value register numbers
- mov bl, ah
- mov ax, bx ; bx <- constant number * 3
- shl ax, 1
- add bx, ax
- add bx, [cb_reg.disp] ; make disp relative
- xor ax, ax
- mov al, [(CODEDEF es:bx).consts.page]
- mov di, ax
- mov ax, [(CODEDEF es:bx).consts.disp]
- cmp [ptype+di], SYMBTYPE
- jne @@error
- mov dx, di
- mov di, [fnv_reg.page]
- mov si, [fnv_reg.disp]
- mov bx, di ; Page number
- call lookup ; search fluid environment for symbol
- or bx, bx ; symbol found in fluid environment?
- je @@notfound
- pop ax ; restore operands
- mov bl, al
- mov dl, [regs+bx.bpage] ; set cdr of fluid var entry to reg
- mov ax, [regs+bx.disp]
- mov [(LISTDEF es:di).cdr.page], dl
- mov [(LISTDEF es:di).cdr.disp], ax
- jmp next_pc
-
- @@error:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "SET-FLUID!", 0
- CODESEG
- jmp src_err
-
- @@notfound:
- pop cx ; restore instruction's operands
- xor ch, ch
- add cx, OFFSET regs ; compute address of source register
- corpage dx ; convert page number to C's notation
- call not_fluidly_bound C, dx, ax, cx
- restore <si>
- sub si, 3 ; retry the set-fluid! operation
- jmp sch_err
- ENDP st_fluid
-
- ;************************************************************************
- ;* fluid-bound? FLUID? reg *
- ;************************************************************************
- PROC fluid_p
- get1op
- save <si>
- mov bx, ax
- add bx, OFFSET regs
- mov ax, [(REG bx).disp]
- mov dx, [(REG bx).page]
- mov di, dx
- cmp [ptype+di], SYMBTYPE
- jne @@error
- mov di, [fnv_reg.page]
- mov si, [fnv_reg.disp]
- push bx
- mov bx, di ; Page number
- call lookup
- or bx, bx
- pop bx
- jz @@notfound
- mov [(REG bx).bpage], T_PAGE*2 ; symbol is fluidly bound
- mov [(REG bx).disp], T_DISP
- jmp next_pc
- @@notfound:
- xor ax, ax
- mov [(REG bx).bpage], al
- mov [(REG bx).disp], ax
- jmp next_pc
- @@error:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "FLUID-BOUND?", 0
- CODESEG
- jmp src_err
- ENDP fluid_p
-
- ;************************************************************************
- ;* al ah *
- ;* Bind fluid variable BIND-FL const, src *
- ;* *
- ;* Purpose: Interpreter support for binding (creating and defining) *
- ;* fluid variables *
- ;* *
- ;* Note: At entry to this routine, es is set to point to the beginning *
- ;* of the page containing the current code block. *
- ;************************************************************************
- PROC bind_fl
- get2op
- save <si>
- mov bl, ah ; copy the source register number
- lea di, [regs+bx]
- mov bl, al ; bx <- constant number * 3
- mov ax, bx
- shl ax, 1
- add bx, ax
- add bx, [cb_reg.disp] ; make disp relative
- xor dx, dx
- mov dl, [(CODEDEF es:bx).consts.page]
- mov ax, [(CODEDEF es:bx).consts.disp]
- mov [tmp_reg.page], dx
- mov [tmp_reg.disp], ax
- lea ax, [tmp_reg]
- call cons C, ax, ax, di ; tmp_reg := (symbol . value)
- lea ax, [tmp_reg]
- lea bx, [fnv_reg]
- call cons C, bx, ax, bx ; FNV := ((symbol . value) FNV)
- jmp next_pc
- ENDP bind_fl
-
- ;************************************************************************
- ;* Unbind fluid variable UNBIND-FL const *
- ;* *
- ;* Purpose: Interpreter support for unbinding (deleting) fluid *
- ;* variables *
- ;* *
- ;* Description: The fluid environment is maintained as an a-list, so *
- ;* dropping fluids consists of cdr-ing down the list for *
- ;* the required number of elements. *
- ;************************************************************************
- PROC unbind_f
- get1op
- save <si>
- mov cx, ax
- mov bl, [fnv_reg.bpage] ; load the fluid environment pointer
- mov di, [fnv_reg.disp]
- @@loop:
- ldpage es, bx
- mov bl, [(LISTDEF es:di).cdr.page]
- mov di, [(LISTDEF es:di).cdr.disp]
- loop @@loop
- mov [fnv_reg.bpage], bl
- mov [fnv_reg.disp], di
- jmp next_pc
- ENDP unbind_f
-
- ;************************************************************************
- ;* Allocate vector VEC-ALLOCATE dest *
- ;* *
- ;* Purpose: Interpreter support for the allocation of vector data *
- ;* objects. *
- ;* *
- ;* Note: Vectors are set to zero after they are allocated to insure *
- ;* that all entries are valid Scheme pointers. Zeroing a *
- ;* vector effectively sets all the entries to nil. *
- ;* If an array were not initialized, the garbage collector *
- ;* would interpret any leftover data as pointers, and *
- ;* might cause the Scheme Virtual Machine to go off the *
- ;* deep end. *
- ;************************************************************************
- PROC vec_allo
- get1op
- save <si>
- mov bx, ax
- add bx, OFFSET regs
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@error
- mov ax, [(REG bx).disp]
- or ax, ax
- jl @@error
- cmp ax, 7fffh / (SIZE POINTER)
- jae @@toobig
- mov cx, ax ; ax <- ax * 3 (multiply number of
- shl ax, 1 ; elements by size of pointer)
- add ax, cx
- mov cx, VECTTYPE
- push bx
- call alloc_block C, bx, cx, ax
- pop bx ; recover address of reg holding vector ptr
- mov ax, [(REG bx).page]
- corpage ax
- call zero_blk C, ax, [(REG bx).disp]
- jmp next_pc
- @@error:
- mov si, [(REG bx).page]
- cmp [ptype+si], BIGTYPE
- je @@toobig
- lea bx, [@@msg]
- DATASEG
- @@msg DB "MAKE-VECTOR", 0
- CODESEG
- jmp src_err
- @@toobig:
- restore <si>
- sub si, 2
- lea ax, [@@msg]
- call disassemble C, ax, si
- mov ax, 1
- mov bx, VECTOR_SIZE_LIMIT_ERROR
- call set_numeric_error C, ax, bx, [tmp_adr]
- jmp sch_err
- ENDP vec_allo
-
- ;************************************************************************
- ;* Vector size VECTOR-SIZE dest *
- ;* *
- ;* Purpose: Interpreter support for the vector-size function to return *
- ;* the number of elements in a vector data object. *
- ;* *
- ;* Description: The number of elements in a vector data object is *
- ;* determined by dividing the number of bytes (obtained *
- ;* from the block header of the vector data object) by the *
- ;* number of bytes in a pointer (3), and subtracting the *
- ;* overhead of the block header (3 bytes). *
- ;************************************************************************
- PROC vec_size
- get1op
- mov bx, ax
- add bx, OFFSET regs
- save <si>
- mov si, [(REG bx).page]
- mov di, [(REG bx).disp]
- cmp [ptype+si], VECTTYPE
- jne @@error
- ldpage es, si
- mov ax, [(VECDEF es:di).len]
- xor dx, dx ; extend to double word
- mov cx, SIZE POINTER
- div cx
- dec ax ; subtract off block overhead
- mov [(REG bx).disp], ax
- mov [(REG bx).bpage], SPECFIX*2
- jmp next_pc
-
- @@error:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "VECTOR-SIZE", 0
- CODESEG
- jmp src_err
- ENDP vec_size
-
- ;************************************************************************
- ;* al ah *
- ;* vector fill vec-fill vect, val *
- ;* *
- ;* Purpose: Scheme intepreter support for the vector-fill operation *
- ;************************************************************************
- PROC vec_fill
- get2op
- save <si>
- xor bx, bx
- mov bl, al ; copy number of register containing vector
- mov di, [regs+bx.disp]
- mov bl, [regs+bx.bpage]
- cmp [ptype+bx], VECTTYPE
- jne @@error
- ldpage es, bx
- mov bl, ah ; copy pointer to fill value
- mov ax, [regs+bx.disp] ; load value to fill array
- mov dl, [regs+bx.bpage]
- mov cx, [(VECDEF es:di).len]
- sub cx, OFFSET (TYPE VECDEF).data
- jle @@done
- @@loop:
- mov [(VECDEF es:di).data.page], dl
- mov [(VECDEF es:di).data.disp], ax
- add di, SIZE POINTER
- sub cx, SIZE POINTER
- jg @@loop
- @@done:
- jmp next_pc
-
- @@error:
- lea bx, [@@msg]
- DATASEG
- @@msg DB "VECTOR-FILL!", 0
- CODESEG
- jmp src_err
- ENDP vec_fill
-
- ;************************************************************************
- ;* al ah *
- ;* (memq obj list) MEMQ dest, src *
- ;* *
- ;* Purpose: Scheme interpreter support for the memq primitive *
- ;************************************************************************
- PROC memq
- get2op
- save <si>
- mov bl, al
- in_memq:
- lea di, [regs+bx] ; destination address in di
- mov al, [(REG di).bpage] ; object pointer in al:dx
- mov dx, [(REG di).disp]
- mov bl, ah
- mov si, [regs+bx.disp] ; list register in bl:si
- mov bl, [regs+bx.bpage]
- jmp @@more
- @@next:
- cmp [s_break], 0
- jne @@break
- mov bl, [(LISTDEF es:si).cdr.page]
- mov si, [(LISTDEF es:si).cdr.disp]
- @@more:
- or bl, bl
- jz @@fail
- cmp [ptype+bx], LISTTYPE
- jne @@fail
- ldpage es, bx
- cmp dx, [(LISTDEF es:si).car.disp]
- jne @@next
- cmp al, [(LISTDEF es:si).car.page]
- jne @@next
-
- mov [(REG di).bpage], bl ; set destination register
- mov [(REG di).disp], si
- jmp next_pc
- @@fail:
- xor ax, ax
- mov [(REG di).bpage], al
- mov [(REG di).disp], ax
- jmp next_pc
- @@break:
- in_shiftbreak:
- mov ax, 3
- call restart C, ax ; link to Scheme debugger
- ENDP memq
-
- ;************************************************************************
- ;* al ah *
- ;* (memv key list) MEMV dest, src *
- ;* key, list *
- ;* *
- ;* Purpose: Scheme interpreter support for the memv primitive *
- ;************************************************************************
- PROC memv
- get2op
- save <si>
- mov bl, al
- mov di, [regs+bx.page]
- test [attrib+di], FIXNUMS or FLONUMS or BIGNUMS or STRINGS
- jnz @@notmemq
- jmp in_memq
- @@notmemq:
- test [attrib+di], FIXNUMS or FLONUMS or BIGNUMS
- jnz @@notmember
- jmp in_member
- @@notmember: ; key is a number
- lea di, [regs+bx] ; di=address of VM reg containing key
- mov bl, ah
- lea si, [regs+bx] ; si=address of VM reg containing list
- push [(REG si).page] ; tempsave "list" VM reg
- push [(REG si).disp]
- jmp @@next
-
- @@break:
- jmp in_shiftbreak
- @@more: ; this list element didn't match, go to the next element
- cmp [s_break], 0 ; shift-break pressed?
- jne @@break
- mov bx, [(REG si).page]
- ldpage es, bx
- mov bx, [(REG si).disp]
- mov cl, [(LISTDEF es:bx).cdr.page]
- mov ch, 0
- mov ax, [(LISTDEF es:bx).cdr.disp]
- mov [(REG si).page], cx
- mov [(REG si).disp], ax
- @@next: ; loop over each element in the list
- mov bx, [(REG si).page]
- cmp bx, NIL_PAGE ; at end of list?
- je @@finished
- cmp [ptype+bx], LISTTYPE ; looking at a cons?
- jne @@finished
- ldpage es, bx ; get cons into memory
- mov bx, [(REG si).disp] ; es:bx=address of cons cell
- mov bl, [(LISTDEF es:bx).car.page]
- mov bh, 0
- test [attrib+bx], FIXNUMS or FLONUMS or BIGNUMS
- jz @@more ; key and list element are both numeric
- mov [tmp_reg.page], bx
- mov bx, [(REG si).disp]
- mov bx, [(LISTDEF es:bx).car.disp]
- mov [tmp_reg.disp], bx
- lea bx, [tmp_reg]
- cmp [(REG di).bpage], SPECFIX*2
- jne @@float ; begin comparison of key and list element
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@float
- ; both key and list element are fixnums
- mov ax, [(REG bx).disp] ; ax = list element,
- cmp ax, [(REG di).disp] ; [di] = key
- jne @@more
- @@found: ; we have a match, copy list object-pointer to VM register containing key
- mov ax, [(REG si).disp]
- mov dx, [(REG si).page]
- mov [(REG di).disp], ax
- mov [(REG di).page], dx
- jmp @@done
- @@finished: ; we have no match, copy '() to VM register containing key
- xor ax, ax
- mov [(REG di).page], ax
- mov [(REG di).disp], ax
- @@done:
- pop [(REG si).disp] ; restore original contents "list" VM reg
- pop [(REG si).page]
- jmp next_pc
- @@float: ; key and list element are not both fixnums, do = operation
- mov ax, EQ_OP
- call arith2 C, ax, di, bx
- or ax, ax
- jge @@couldbe
- pop [(REG si).disp] ; restore original contents "list" VM reg
- pop [(REG si).page]
- jmp sch_err
- @@couldbe:
- jg @@found ; ax positive means "true"
- jmp @@more
- ENDP memv
-
- ;************************************************************************
- ;* al ah *
- ;* (member key list) MEMBER dest, src *
- ;* key, list *
- ;* *
- ;* Purpose: Scheme interpreter support for the member primitive *
- ;************************************************************************
- PROC member
- get2op
- save <si>
- mov bl, al
- mov di, [regs+bx.page] ; load search object's page number
- test [attrib+di], FIXNUMS or SYMBOLS or CONTINU or CLOSURE or PORTS or CODE or CHARS
- jz @@notmemq
- jmp in_memq
- @@notmemq:
- in_member:
- lea di, [regs+bx]
- mov cl, [(REG di).bpage] ; load pointer to object in cl:dx
- mov dx, [(REG di).disp]
- mov bl, cl
- mov ch, [ptype+bx] ; load type code of search object
- mov bl, ah ; copy pointer to search list
- mov si, [regs+bx.disp] ; load contents of "list" register
- mov bl, [regs+bx.bpage]
- jmp @@go
- @@more:
- mov ax, bx
- mov bl, [(LISTDEF es:si).car.page]
- cmp ch, [ptype+bx]
- jne @@nxt
- push ax cx dx si ; save registers across call
- xor dx, dx
- mov dl, [(LISTDEF es:si).car.page]
- mov ax, [(LISTDEF es:si).car.disp]
- mov [tmp_reg.page], dx ; tmp_reg := (car list)
- mov [tmp_reg.disp], ax
- lea bx, [tmp_reg]
-
- call sequal_p C, di, bx
- pop si dx cx bx
- ldpage es, bx ; restore page paragraph address
- or ax, ax
- jne @@found
- @@nxt:
- cmp [s_break], 0 ; has shift-break key been depressed?
- jne @@break
- mov bl, [(LISTDEF es:si).cdr.page]
- mov si, [(LISTDEF es:si).cdr.disp]
- @@go:
- or bl, bl ; nil pointer?
- je @@fail
- cmp [ptype+bx], LISTTYPE
- jne @@fail
- ldpage es, bx
- cmp dx, [(LISTDEF es:si).car.disp] ; does displacement field of car match obj?
- jne @@more
- cmp cl, [(LISTDEF es:si).car.page] ; does page field of car match obj?
- je @@found
- jmp @@more
- @@found: ; "eq" match found-- return pointer to current list cell
- mov [(REG di).bpage], bl
- mov [(REG di).disp], si
- jmp next_pc
- @@fail: ; no match-- return 'nil
- xor ax, ax
- mov [(REG di).bpage], al
- mov [(REG di).disp], ax
- jmp next_pc
- @@break:
- jmp in_shiftbreak
- ENDP member
-
- ;************************************************************************
- ;* al ah *
- ;* (assq obj list) ASSQ obj, list *
- ;* *
- ;* Purpose: Scheme interpreter support for the assq primitive *
- ;************************************************************************
- PROC assq
- get2op
- save <si>
- in_assq:
- mov bl, ah ; copy the list register number
- mov si, [regs+bx.page]
- cmp [ptype+si], LISTTYPE
- jne @@fail
- ldpage es, si
- mov di, si
- mov si, [regs+bx.disp] ; list operand in es:si
- mov bl, al ; search object in dx:ax
- mov dx, [regs+bx.page]
- mov ax, [regs+bx.disp]
- push bx
- mov bx, di ; Reload page number
- call lookup ; search list for eq? comparison of obj
- pop si
- mov [regs+si.bpage], bl ; store result
- mov [regs+si.disp], di
- jmp next_pc
- @@fail: ; error - return nil
- mov bl, al ; copy register number
- xor ax, ax
- mov [regs+bx.bpage], al
- mov [regs+bx.disp], ax
- jmp next_pc
- ENDP assq
-
- ;************************************************************************
- ;* al ah *
- ;* (assv key alist) ASSV key, alist *
- ;* *
- ;* Purpose: Scheme interpreter support for the assv primitive *
- ;************************************************************************
- PROC assv
- get2op
- save <si>
- mov bl, al ; key register
- mov di, [regs+bx.page]
- test [attrib+di], FIXNUMS or FLONUMS or BIGNUMS or STRINGS
- jnz @@notassq
- jmp in_assq
- @@notassq:
- test [attrib+di], FIXNUMS or FLONUMS or BIGNUMS
- jnz @@notassoc
- jmp in_assoc
- @@notassoc: ; key is a number
- lea di, [regs+bx] ; di=address of VM reg containing key
- mov bl, ah
- lea si, [regs+bx] ; si=address of VM reg containing list
- push [(REG si).page] ; tempsave "alist" VM reg
- push [(REG si).disp]
- jmp @@next
-
- @@break:
- jmp in_shiftbreak
- @@more:
- cmp [s_break], 0 ; shift-break pressed?
- jne @@break
- mov bx, [(REG si).page]
- ldpage es, bx ; get toplevel cons back into es:bx
- mov bx, [(REG si).disp]
- xor dx, dx
- mov dl, [(LISTDEF es:bx).cdr.page] ; cdr down the alist
- mov ax, [(LISTDEF es:bx).cdr.disp]
- mov [(REG si).page], dx
- mov [(REG si).disp], ax
- @@next: ; loop over each element in the list
- mov bx, [(REG si).page]
- cmp bx, NIL_PAGE ; at end of list?
- jne @@stillok
- jmp @@fail
- @@stillok:
- cmp [ptype+bx], LISTTYPE ; looking at a cons?
- jne @@fail
- ldpage es, bx ; get toplevel cons into es:bx
- mov bx, [(REG si).disp]
- push bx
- mov bl, [(LISTDEF es:bx).car.page]
- mov bh, 0
- cmp [ptype+bx], LISTTYPE ; is car of toplevel cons also a cons?
- je @@chain
- @@popit:
- pop bx ; normalize stack
- @@more1:
- jmp @@more ; look at next toplevel cons
- @@chain:
- mov dx, bx
- pop bx ; (es:bx=address of toplevel cons again)
- mov bx, [(LISTDEF es:bx).car.disp] ; dx:bx=object ptr to 2nd level cons
- ldpage es, dx ; es:bx=address of 2nd level cons cell
- push bx
- mov bl, [(LISTDEF es:bx).car.page]
- mov bh, 0
- test [attrib+bx], FIXNUMS or FLONUMS or BIGNUMS ; is its car numeric?
- jz @@popit
- mov [tmp_reg.page], bx ; yes, move car ptr into tmp_reg
- pop bx ; (es:bx=address of 2nd level cons again)
- mov bx, [(LISTDEF es:bx).car.disp]
- mov [tmp_reg.disp], bx
- lea bx, [tmp_reg]
-
- cmp [(REG di).bpage], SPECFIX*2
- jne @@float
- cmp [(REG bx).bpage], SPECFIX*2
- jne @@float
- ; both key and list element are fixnums
- mov ax, [(REG bx).disp] ; ax = list element,
- cmp ax, [(REG di).disp] ; [di] = key
- jne @@more1
- jmp @@found
- @@fail: ; return nil
- xor ax, ax
- mov [(REG di).page], ax
- mov [(REG di).disp], ax
- @@done:
- pop [(REG si).disp] ; restore original contents "alist" VM reg
- pop [(REG si).page]
- jmp next_pc
- @@found: ; copy list object-pointer to key
- mov bx, [(REG si).page]
- ldpage es, bx
- mov bx, [(REG si).disp] ; es:bx=address of toplevel cons
- xor dx, dx
- mov dl, [(LISTDEF es:bx).car.page]
- mov ax, [(LISTDEF es:bx).car.disp] ; move car of this cons to dest. register
- mov [(REG di).page], dx
- mov [(REG di).disp], ax
- jmp @@done
- @@float:
- mov ax, EQ_OP
- call arith2 C, ax, di, bx
- or ax, ax
- jge @@faillo2
- jmp sch_err
- @@faillo2:
- jg @@found ; ax positive means "true"
- jmp @@more
- ENDP assv
-
- ;************************************************************************
- ;* al ah *
- ;* (assoc obj list) ASSOC obj, list *
- ;* *
- ;* Purpose: Scheme interpreter support for the assoc primitive *
- ;* *
- ;* Register Usage: dx - address of destination register *
- ;* es:si - pointer to current list cell *
- ;************************************************************************
- PROC assoc
- get2op
- save <si>
- mov bl, al ; copy search object's register number
- mov si, [regs+bx.page]
- test [attrib+si], FIXNUMS or SYMBOLS or CONTINU or CLOSURE or PORTS or CODE or CHARS
- jz @@notassq
- jmp in_assq
- in_assoc:
- @@notassq:
- lea dx, [regs+bx] ; copy obj's reg address in dx
- mov bl, ah ; copy list register number
- mov si, [regs+bx.disp]
- mov bl, [regs+bx.bpage]
- @@more:
- or bl, bl ; end of list ?
- jnz @@stillok
- @@tofail:
- jmp @@fail
- @@stillok:
- cmp [ptype+bx], LISTTYPE
- jne @@tofail
- ldpage es, bx
- mov ax, bx
- mov bl, [(LISTDEF es:si).car.page]
- cmp [ptype+bx], LISTTYPE ; does car point to list cell?
- jne @@notlist
- mov di, [(LISTDEF es:si).car.disp]
- push ax
- ldpage es, bx
- xor cx, cx
- mov cl, [(LISTDEF es:di).car.page] ; copy car field into tmp_reg
- mov ax, [(LISTDEF es:di).car.disp]
- mov [tmp_reg.page], cx
- mov [tmp_reg.disp], ax
- lea ax, [tmp_reg]
- push dx
- call sequal_p C, ax, dx
- pop dx
- pop bx ; restore page num
- ldpage es, bx
- or ax, ax ; were pointers equal?
- jne @@found
- @@notlist:
- xor bx, bx
- mov bl, [(LISTDEF es:si).cdr.page] ; follow cdr field
- mov si, [(LISTDEF es:si).cdr.disp]
- cmp [s_break], 0 ; has the shift-break key been depressed?
- jne @@shiftbreak
- jmp @@more
- @@shiftbreak:
- jmp in_shiftbreak
- @@found: ; pointers "equal"-- return pointer to car field of current list cell
- mov di, dx ; copy destination register address to di
- mov dl, [(LISTDEF es:si).car.page] ; return cdr field of list cell
- mov ax, [(LISTDEF es:si).car.disp]
- mov [(REG di).bpage], dl
- mov [(REG di).disp], ax
- jmp next_pc
- @@fail: ; return nil
- mov di, dx
- xor ax, ax
- mov [(REG di).page], ax
- mov [(REG di).disp], ax
- jmp next_pc
- ENDP assoc
- END